package xml.resource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Put;
import org.restlet.resource.ResourceException;
import xml.form.Form;
import xml.model.Groupe;
import xml.model.Contact;
import xml.validator.LengthValidator;
import xml.validator.LongRangeValidator;
import xml.validator.NotEmptyValidator;

/**
 * Resource correspondant à un groupe de contacts
 * Méthodes: GET, DELETE, PUT
 * @author marya
 */
public class GroupeResource extends AbstractResource {

    private Groupe groupe;

    public GroupeResource() {
        super();
    }

    @Override
    protected void doInit() {
        Long idGroupe;

        Connection connexion = null;
        final String sqlGroupe = " SELECT * FROM groupe WHERE id_groupe= ";

        String idGroupeAttribute = getRequest().getAttributes().get("idGroupe").toString();
        LongRangeValidator longRangeValidator = new LongRangeValidator(1l, null);

        //Validation de l'id de la promotion
        if (longRangeValidator.isValid(idGroupeAttribute)) {
            idGroupe = Long.parseLong(idGroupeAttribute);
        } else {
            errors.add(new ResourceError("invalidGroupe"));
            throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST);
        }

        try {
            /**
             * On permet n'importe quel id de groupe pour que le message d'erreur HTTP
             * CLIENT_ERROR_BAD_REQUEST renseigne que cette resource est seulement pour les groupes
             * et non pour les promotions
             */
            connexion = database.getNewConnection();
            ResultSet rs = connexion.createStatement().executeQuery(sqlGroupe + idGroupe);
            if (rs != null && rs.next()) {
                if (rs.getString("url") != null) {
                    throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Invalid Request for attempting a promotion ");
                } else {
                    groupe = new Groupe(rs.getInt("id_groupe"), rs.getString("nom"), new ArrayList<Contact>());
                    groupe.setUri(getRootRef().getHostIdentifier() + "/groupes/" + idGroupe);
                }
                DbUtils.closeQuietly(connexion);
            } else {
                DbUtils.closeQuietly(connexion);
                setExisting(false);
            }

        } catch (SQLException e) {
            e.printStackTrace();
            DbUtils.closeQuietly(connexion);
            throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e);
        }
    }

    @Get
    public Representation doGet() throws Exception {
        return groupe.toXML();
    }

    @Put
    public Representation doPut(Representation entity) throws Exception {
        Representation response = null;
        Form form = getNewForm(entity);
        Connection connexion = null;
        final String sqlPromotion = "UPDATE groupe SET nom=? WHERE id_groupe = " + groupe.getIdGroupe();

        if (!form.isValid()) {
            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            for (String error : form.getMessages()) {
                errors.add(new ResourceError(error));
            }
        } else {
            String nom = form.getFirstValue("nom");
            connexion = database.getNewConnection();
            QueryRunner qR = new QueryRunner();
            Integer result = qR.update(connexion, sqlPromotion, nom);
            Groupe g = new Groupe(result, nom, null);
            response = g.toXML();
        }
        DbUtils.closeQuietly(connexion);
        if (!errors.isEmpty()) {
            response = ResourceError.getListRepresentation(errors);
        }
        return response;
    }

    @Delete
    public void doDelete() throws Exception {
        final String selectContacts = "SELECT DISTINCT COUNT(id_contact) AS nb_contacts FROM contact_groupe WHERE id_groupe = " + groupe.getIdGroupe();
        final String sqlContact = "DELETE FROM contact_groupe WHERE id_groupe = " + groupe.getIdGroupe();
        final String sqlGroupe = "DELETE FROM groupe WHERE id_groupe = " + groupe.getIdGroupe() + " AND url IS NULL";

        Connection connexion = null;
        try {
            connexion = database.getNewConnection();
            connexion.setAutoCommit(false);
            QueryRunner queryRunner = new QueryRunner();

            ResultSet rs = connexion.createStatement().executeQuery(selectContacts);

            int res;
            if (rs.next()) {
                int nbContacts = rs.getInt("nb_contacts");
                if (nbContacts > 0) {
                    res = queryRunner.update(connexion, sqlContact);
                }
            }

            res = queryRunner.update(connexion, sqlGroupe);
            if (res < 1) {
                DbUtils.rollbackAndCloseQuietly(connexion);
                setStatus(Status.SERVER_ERROR_INTERNAL, "Impossible de supprimer la ressource représentant ce groupe");
            } else {
                connexion.commit();
                DbUtils.closeQuietly(connexion);
                setStatus(Status.SUCCESS_NO_CONTENT);
            }

        } catch (SQLException e) {
            DbUtils.rollbackAndCloseQuietly(connexion);
            throw e;
        }
    }

    @SuppressWarnings("unchecked")
    private Form getNewForm(Representation entity) {
        xml.form.Form form = new xml.form.Form(entity);
        form.addValidators("nom", new NotEmptyValidator(), new LengthValidator(255));
        return form;
    }

    @Override
    protected void doCatch(Throwable throwable) {
        super.doCatch(throwable);
        throwable.printStackTrace();
    }
}
